<template>
  <div class="plandiv">
    <div v-for="item in data" :key="item.id" class="forDiv">
      <div class="groupDiv">
        <div class="groupBackColor">
          <div style="width: 20%">
            <el-select v-model="item.matchGroup" placeholder="请选择" style="
                float: left;
                margin-right: 10px;
                margin-left: 10px;
                min-width: 100px;
              ">
              <el-option v-for="group in matchingGroup" :key="group.value" :label="group.label" :value="group.value" />
            </el-select>
          </div>
          <div style="width: 80%">
            <div class="buttonStyle">
              <el-button icon="CirclePlus" plain @click="addGroup(item)">新增分组</el-button>
              <el-button icon="Plus" plain @click="addItem(item)">新增条件</el-button>
              <el-button v-if="item.level !== 1" type="danger" icon="Delete" @click="deleteGroup(item)">删除分组</el-button>
              <!-- 当前组id：{{ item.id }} -->
            </div>
          </div>
        </div>
        <div class="itemBackColor" v-for="whereItem in item.matchingWhere" :key="whereItem.id">
          <!-- 匹配字段 -->
          <el-select v-model="whereItem.fieldKey" placeholder="请选择匹配条件"
            @change="fieldChange(whereItem.fieldKey, whereItem)" style="width: 240px">
            <el-option v-for="where in matchFieldData" :key="where.value" :label="where.label" :value="where.value" />
          </el-select>
          <!-- 匹配等式 -->
          <el-select v-model="whereItem.matchEquationKey" placeholder="请选择等式" style="width: 240px">
            <el-option v-for="equation in matchFieldData.find(
              (f) => f.value === whereItem.fieldKey
            )?.matchEquationOptions" :key="equation.value" :label="equation.label" :value="equation.value" />
          </el-select>

          <!--数字输入框-->
          <el-input-number v-model="whereItem.matchDataKey" :step="1" min="0" max="200" step-strictly
            style="width: 240px" v-if="whereItem.showDataControl === showDataControlEnum.Number" />

          <!--单选复选框-->
          <el-select v-else-if="
            whereItem.showDataControl === showDataControlEnum.RadioSelect
          " v-model="whereItem.matchDataName" placeholder="请选择" style="width: 240px">
            <el-option v-for="position in whereItem.bindDataSource" :key="position.value" :label="position.label"
              :value="position.value" />
          </el-select>
          <!--时间选择-->
          <el-date-picker v-else-if="
            whereItem.showDataControl === showDataControlEnum.DateTimes
          " v-model="whereItem.matchDataKey" type="date" style="width: 240px" format="YYYY-MM-DD"
            value-format="YYYY-MM-DD" placeholder="请选择时间" />
          <!--输入框-->
          <el-input v-else-if="whereItem.showDataControl === showDataControlEnum.Input" v-model="whereItem.matchDataKey"
            maxlength="20" style="width: 240px" placeholder="请输入" clearable />
          <!--弹出层-->
          <el-input v-else-if="
            whereItem.showDataControl === showDataControlEnum.RadioLayer ||
            whereItem.showDataControl === showDataControlEnum.MultipleLayer
          " v-model="whereItem.matchDataName" style="width: 240px" readonly>
            <template #append><el-button style="background-color: #409eff; color: white" type="primary"
                @click="selectLayerClick(whereItem)">选择</el-button></template>
          </el-input>
          <el-button type="danger" icon="Delete" plain size="small" style="margin-left: 10px"
            @click="deleteItem(whereItem, item)">删除条件</el-button>
          <!-- 当前项id：{{ whereItem.id }} -->
        </div>
        <xc-match v-if="item.children && item.children.length" :data="item.children" :matchFieldData="matchFieldData"
          :matchEquation="matchEquation" :menuId="menuId" :corporationKey="corporationKey" :systemKey="systemKey" />
      </div>
    </div>
  </div>
  <userLayout :isVisibles="userModel.Visibles" :userId="userModel.userId" :menuId="userModel.menuId"
    :selectType="userModel.selectType" @closeBnt="colosDialogClick" @confirmBnt="confirmClick"></userLayout>
  <departmentLayout :isVisibles="departmentModel.Visibles" :depId="departmentModel.depId"
    :corporationKey="departmentModel.corporationKey" :selectType="departmentModel.selectType"
    @closeBnt="colosDialogClick" @confirmBnt="confirmClick"></departmentLayout>
  <corporationLayout :isVisibles="corporationModel.Visibles" :corporationKey="corporationModel.corporationKey"
    @closeBnt="colosDialogClick" @confirmBnt="confirmClick"></corporationLayout>
  <systemLayout :isVisibles="systemModel.Visibles" :corporationKey="systemModel.corporationKey"
    :systemKey="systemModel.systemKey" @closeBnt="colosDialogClick" @confirmBnt="confirmClick"></systemLayout>
  <roleLayout :isVisibles="roleModel.Visibles" :corporationKey="roleModel.corporationKey"
    :systemKey="roleModel.systemKey" :roleId="roleModel.roleId" :selectType="roleModel.selectType"
    @closeBnt="colosDialogClick" @confirmBnt="confirmClick">
  </roleLayout>
</template>
<script lang="ts">
import { AnalysisMatchFormula, GetSelectData } from "@/api/match";
import {
  matchingData,
  matchingGroup,
  randamId,
  matchingWhereData,
  showDataControlEnum,
  matchResultData,
  matchingSelectExtendOutPut,
  showControlDataSourceEnum,
  SelectTypeEnum,
} from "@/model/match";
import { selectOutPut } from "@/model/public/selectModel";
import { ElMessage } from "element-plus";
import { plus } from "number-precision";
import { ref, defineComponent, PropType, reactive } from "vue";
import userLayout from "@/components/user.vue";
import departmentLayout from "@/components/department.vue";
import corporationLayout from "@/components/corporation.vue";
import systemLayout from "@/components/system.vue";
import roleLayout from "@/components/role.vue";

export default defineComponent({
  name: "xc-match",
  props: {
    data: {
      type: Object as PropType<matchingData[]>,
      required: true,
    },
    matchFieldData: {
      type: Object as PropType<matchingSelectExtendOutPut[]>,
      required: true,
    },
    matchEquation: {
      type: Object as PropType<selectOutPut[]>,
      required: true,
    },
    menuId: {
      type: String,
      required: true,
    },
    corporationKey: {
      type: String,
      required: true,
    },
    systemKey: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    //用户模型控制
    const userModel = reactive({
      Visibles: false,
      userId: "",
      menuId: props.menuId,
      selectType: SelectTypeEnum.Radio,
    });
    //部门模型控制
    const departmentModel = reactive({
      Visibles: false,
      depId: "",
      selectType: SelectTypeEnum.Radio,
      corporationKey: props.corporationKey,
    });
    //公司模型控制
    const corporationModel = reactive({
      Visibles: false,
      corporationKey: props.corporationKey,
    });
    //系统模型控制
    const systemModel = reactive({
      Visibles: false,
      systemKey: props.systemKey,
      corporationKey: props.corporationKey,
    });
    //角色模型控制
    const roleModel = reactive({
      Visibles: false,
      systemKey: props.systemKey,
      corporationKey: props.corporationKey,
      roleId: "",
      selectType: SelectTypeEnum.Radio,
    });
    //最多组
    const maxGroup = ref<number>(5);
    //最多层级
    const maxLevel = ref<number>(3);
    //最多条件
    const maxWhere = ref<number>(10);

    // 添加组事件
    const addGroup = function (item: matchingData) {
      //获取当前组的长度
      const listGroupLength = item.children.length;

      //添加前验证最多添加多少层级
      if (item.level >= maxLevel.value) {
        ElMessage({
          message: "最多添加" + maxLevel.value + "级",
          type: "warning",
        });
        return;
      }

      //添加前验证能添加多少组
      if (listGroupLength >= maxGroup.value) {
        ElMessage({
          message: "每层下最多添加" + maxGroup.value + "个组",
          type: "warning",
        });
        return;
      }

      //当前组必须要有条件才能添加下级组
      if (item.matchingWhere.length == 0) {
        ElMessage({
          message: "当前组下无任何条件,不能添加分组！",
          type: "warning",
        });
        return;
      }

      //组织要添加节点的数据
      var groupId = item.id + "-" + (listGroupLength + 1);
      var groupPid = item.id;
      var groupLevel = item.level + 1;

      //找到对应的下标
      const index = props.data.findIndex((s) => {
        if (s.id === item.id) {
          return true;
        }
      });

      //精确插入当前节点及插入位置
      var indexLength = listGroupLength + 1;
      item.children.splice(plus(...[index, indexLength]), 0, {
        id: groupId,
        pid: groupPid,
        matchGroup: "Or",
        level: groupLevel,
        matchingWhere: [
          {
            id: randamId().toString(),
            fieldKey: "",
            matchDataKey: "",
            matchDataName: "",
            matchEquationKey: "",
            showDataControl: showDataControlEnum.Input,
            showControlDataSourceType: showControlDataSourceEnum.HandInput,
            bindDataSource: [],
          },
        ],
        children: [],
      });
    };

    // 删除组
    const deleteGroup = function (item: matchingData) {
      GetGroupSpliceIndex(item.id, props.data);
    };

    //递归删除组
    const GetGroupSpliceIndex = (id: string, list: matchingData[]) => {
      //找到删除数据下标
      const index = list.findIndex((p: { id: string }) => {
        if (p.id === id) {
          return true;
        }
      });
      if (index === -1) GetGroupSpliceIndex(id, list[0].children);
      list.forEach((f: { id: string }) => {
        if (f.id == id) {
          list.splice(index, 1);
        }
      });
    };

    //添加项事件
    const addItem = function (item: matchingData) {
      if (item.matchingWhere.length > maxWhere.value) {
        ElMessage({
          message: "每层下最多添加" + maxWhere.value + "组条件",
          type: "warning",
        });
        return;
      }
      item.matchingWhere.push({
        id: randamId().toString(),
        fieldKey: "",
        matchDataKey: "",
        matchDataName: "",
        matchEquationKey: "",
        showDataControl: showDataControlEnum.Input,
        showControlDataSourceType: showControlDataSourceEnum.HandInput,
        bindDataSource: [],
      });
    };

    // 删除项
    const deleteItem = function (item: matchingWhereData, data: matchingData) {
      GetItemSpliceIndex(item.id, data);
    };

    //递归删除项
    const GetItemSpliceIndex = (id: string, list: any) => {
      //找到删除数据下标
      const index = list.matchingWhere.findIndex((p: { id: string }) => {
        if (p.id === id) {
          return true;
        }
      });
      if (index === -1) GetItemSpliceIndex(id, list.children);
      list.matchingWhere.forEach((f: { id: string }) => {
        if (f.id == id) {
          //删除当前项
          list.matchingWhere.splice(index, 1);
          if (list.matchingWhere.length == 0 && list.children.length == 0) {
            var parentGroup = props.data.filter((s) => s.id == list.pid);
            //当前组下无任何项并且层级不等于1，删除当前组
            if (parentGroup.length == 0 && list.level !== 1) {
              GetGroupSpliceIndex(list.id, props.data);
            }
          }
        }
      });
    };

    //匹配字段选择事件
    const selectList = ref<selectOutPut[]>([]);
    const fieldChange = (value: string, item: matchingWhereData) => {
      const model = props.matchFieldData.find(
        (f: { value: string }) => f.value === value
      ) as matchingSelectExtendOutPut;
      item.showDataControl = model.showDataControl;
      item.showControlDataSourceType = model.showControlDataSource;
      if (model.showDataControl === showDataControlEnum.RadioSelect) {
        GetSelectData({ showControlDataSourceEnum: model.showControlDataSource }).then(({ data, code, msg }) => {
          if (code === 200) {
            selectList.value = data;
            item.bindDataSource = data;
          }
          else {
            selectList.value = [];
            ElMessage.error(msg);
          }
        })
      }
      else {
        selectList.value = [];
      }
      item.matchEquationKey = "";
      item.matchDataKey = "";
      item.matchDataName = "";
    };

    //记录点击当前数据的id(条件项id)
    const matchingWhereItemId = ref<string>("");

    //选择弹出层事件
    const selectLayerClick = function (item: matchingWhereData) {
      //人员选择
      if (
        item.showControlDataSourceType === showControlDataSourceEnum.Personnel
      ) {
        userModel.Visibles = true;
        userModel.userId = item.matchDataKey;
        userModel.menuId = props.menuId;
        userModel.selectType =
          item.showDataControl === showDataControlEnum.RadioLayer
            ? SelectTypeEnum.Radio
            : SelectTypeEnum.Multiple;
        matchingWhereItemId.value = item.id;
      }

      //部门选择
      if (
        item.showControlDataSourceType === showControlDataSourceEnum.Department
      ) {
        departmentModel.Visibles = true;
        departmentModel.depId = item.matchDataKey;
        departmentModel.corporationKey = props.corporationKey;
        departmentModel.selectType =
          item.showDataControl === showDataControlEnum.RadioLayer
            ? SelectTypeEnum.Radio
            : SelectTypeEnum.Multiple;
        matchingWhereItemId.value = item.id;
      }
      //公司选择
      if (
        item.showControlDataSourceType === showControlDataSourceEnum.Corporation
      ) {
        corporationModel.Visibles = true;
        corporationModel.corporationKey = item.matchDataKey;
        matchingWhereItemId.value = item.id;
      }
      //系统选择
      if (item.showControlDataSourceType === showControlDataSourceEnum.System) {
        systemModel.Visibles = true;
        systemModel.corporationKey = props.corporationKey;
        systemModel.systemKey = item.matchDataKey;
        matchingWhereItemId.value = item.id;
      }
      //角色选择
      if (
        item.showControlDataSourceType === showControlDataSourceEnum.UserRole
      ) {
        roleModel.Visibles = true;
        roleModel.corporationKey = props.corporationKey;
        roleModel.systemKey = props.systemKey;
        roleModel.roleId = item.matchDataKey;
        roleModel.selectType =
          item.showDataControl === showDataControlEnum.RadioLayer
            ? SelectTypeEnum.Radio
            : SelectTypeEnum.Multiple;
        matchingWhereItemId.value = item.id;
      }
    };

    //关闭弹窗方法
    const colosDialogFunction = () => {
      userModel.Visibles = false;
      departmentModel.Visibles = false;
      corporationModel.Visibles = false;
      systemModel.Visibles = false;
      roleModel.Visibles = false;
    };

    //关闭弹出层
    const colosDialogClick = function () {
      colosDialogFunction();
    };

    //确认选择
    const confirmClick = function (item: any) {
      findTreeNodeById(props.data, matchingWhereItemId.value, item);
      colosDialogFunction();
    };

    //递归赋值
    function findTreeNodeById(
      list: matchingData[],
      matchingWhereItemId: string,
      item: any
    ) {
      list.forEach((element) => {
        element.matchingWhere.forEach((w) => {
          if (w.id === matchingWhereItemId) {
            w.matchDataKey = item.key;
            w.matchDataName = item.value;
          }
        });

        if (element.children.length > 0) {
          findTreeNodeById(element.children, matchingWhereItemId, item);
        }
      });
    }

    //验证条件是否为空
    const matchStr = ref<string>("");
    const matchResult = reactive<matchResultData>({
      isSuccess: false,
      msg: "",
      ruleExpression: {
        analysisRule: "",
        analysisRule_CN: "",
      },
      matchRuleJson: "",
    });
    const GetMatchData = async function (menuKey: string, ruleType: number) {
      const isTrueArray = ref<boolean[]>([]);
      matchStr.value = "";
      if (
        props.data[0].children.length === 0 &&
        props.data[0].matchingWhere.length === 0
      ) {
        matchResult.isSuccess = false;
        matchResult.ruleExpression = { analysisRule: "", analysisRule_CN: "" };
        matchResult.msg = "请添加匹配条件";
        return matchResult;
      }
      VerifyFunction(props.data, isTrueArray.value);
      var machtData = JSON.stringify(props.data);
      const trueArray = isTrueArray.value?.filter((f) => f === true);
      console.log(matchStr.value);
      if (trueArray.length > 0) {
        // ElMessage({
        //   message: "匹配条件未填写完整",
        //   type: "warning",
        // });
        matchResult.isSuccess = false;
        matchResult.ruleExpression = { analysisRule: "", analysisRule_CN: "" };
        matchResult.msg = "匹配条件未填写完整";
      } else {
        await AnalysisMatchFormula({
          matchFormula: machtData,
          menuId: menuKey,
          ruleType: ruleType,
        })
          .then((res) => {
            matchResult.isSuccess = true;
            matchResult.ruleExpression = {
              analysisRule: res.data[0].analysisRule,
              analysisRule_CN: res.data[0].analysisRule_CN,
            };
            matchResult.msg = "设置成功";
            matchResult.matchRuleJson = machtData;
          })
          .catch(() => {
            matchResult.isSuccess = false;
            matchResult.ruleExpression = {
              analysisRule: "",
              analysisRule_CN: "",
            };
            matchResult.msg = "设置失败";
          });
      }
      return matchResult;
    };

    //递归验证
    const VerifyFunction = function (
      list: matchingData[],
      isTrueArray: boolean[]
    ) {
      list.forEach((element) => {
        const count = ref<number>(0);
        matchStr.value = matchStr.value + "( ";
        element.matchingWhere.forEach((w) => {
          count.value++;
          //const zcount = element.matchingWhere.length;
          //是否在组项的开始加括号
          // if (count.value === 1) {
          //   matchStr.value = matchStr.value + "( ";
          // }
          const matchWhere = w.fieldKey + w.matchEquationKey + w.matchDataName;
          if (element.matchGroup === "And") {
            if (count.value > 1) {
              matchStr.value = matchStr.value + " && " + matchWhere;
            } else {
              matchStr.value = matchStr.value + matchWhere;
            }
          } else {
            if (count.value > 1) {
              matchStr.value = matchStr.value + " || " + matchWhere;
            } else {
              matchStr.value = matchStr.value + matchWhere;
            }
          }
          //判断结果类型
          if (
            w.showDataControl == showDataControlEnum.DateTimes ||
            w.showDataControl == showDataControlEnum.Input ||
            w.showDataControl == showDataControlEnum.Number
          ) {
            w.matchDataName = w.matchDataKey;
          }
          //是否在组项的结束加括号
          // if (count.value === zcount) {
          //   matchStr.value = matchStr.value + " )";
          // }
          if (
            w.matchEquationKey.length == 0 ||
            (w.matchDataName.length == 0 && w.matchDataKey.length == 0) ||
            w.fieldKey.length == 0
          ) {
            isTrueArray.push(true);
            return;
          }
        });
        if (element.children.length === 0) {
          const kh = ref("");
          for (let i = 0; i < element.level; ++i) {
            kh.value = kh.value + " )";
          }
          matchStr.value = matchStr.value + kh.value;
        }
        if (element.children.length > 0) {
          if (element.matchGroup === "And") {
            matchStr.value = matchStr.value + " && ";
          } else if (element.matchGroup === "Or") {
            matchStr.value = matchStr.value + " || ";
          }
          VerifyFunction(element.children, isTrueArray);
        }
      });
    };
    return {
      matchingGroup,
      showDataControlEnum,
      userModel,
      departmentModel,
      corporationModel,
      systemModel,
      roleModel,
      selectList,
      addGroup,
      addItem,
      deleteItem,
      deleteGroup,
      GetMatchData,
      fieldChange,
      selectLayerClick,
      colosDialogClick,
      confirmClick,
    };
  },
  components: {
    userLayout,
    departmentLayout,
    corporationLayout,
    systemLayout,
    roleLayout,
  },
});
</script>

<style scoped>
/* 最外层样式 */
.plandiv {
  background-color: white;
  height: auto;
}

/* 循环层样式 */
.forDiv {
  overflow-y: auto;
}

/* 分组样式 */
.groupDiv {
  border: 1px solid #919aa3;
  width: auto;
  height: auto;
  margin-top: 5px;
  margin-bottom: 10px;
}

.groupDiv>*:not(:first-child) {
  margin-right: 20px;
  margin-left: 20px;
}

/* 组条件背景色 */
.groupBackColor {
  background-color: #919aa3;
  height: 50px;
  line-height: 50px;
  display: flex;
  width: 100%;
  justify-content: center;
  align-items: center;
}

/* 项背景色 */
.itemBackColor {
  height: 46px;
  display: -webkit-box;
  margin-left: 20px;
  margin-right: 20px;
  display: flex;
  align-items: center;
}

.itemBackColor>*:not(:first-child) {
  margin-left: 10px;
}

/* 按钮样式 */
.buttonStyle {
  text-align: left;
  margin-left: 20px;
}
</style>